﻿#include "stdafx.h"
#include "GeoQip.h"
#include "OptionsQip.h"

const std::string GEOQIP_API_KEY	= "AQIAAD9Pe+6mvrUHhr9uRVQAfJx8NFKz";
const std::string GEOQIP_REFERRER	= "GeoQip";

CQipPlugin::CQipPlugin()
	: CPluginBase(GEOQIP_API_KEY, GEOQIP_REFERRER)
	, m_nUserPicture(0)
	, m_pPluginSpecific(NULL)
{
	::ZeroMemory(&pluginInfo, sizeof(pluginInfo));
	::ZeroMemory(&bInfo, sizeof(bInfo));
}

STDMETHODIMP_(PluginInfo*) CQipPlugin::GetPluginInfo()
{
	if (pluginInfo.DllHandle == NULL)
	{
		WCHAR buf[MAX_PATH];
		::GetModuleFileName(WTL::ModuleHelper::GetModuleInstance(), buf, MAX_PATH);
		pluginInfo.DllPath          = ::SysAllocString(ATL::CT2WEX<MAX_PATH>(buf));
		pluginInfo.QipSdkVerMajor   = QIP_SDK_VER_MAJOR;
		pluginInfo.QipSdkVerMinor   = QIP_SDK_VER_MINOR;
		pluginInfo.PlugVerMajor     = VERSION_MAJOR;
		pluginInfo.PlugVerMinor     = VERSION_MINOR;
		pluginInfo.PluginName       = ::SysAllocString(_VERSION_UNICODE(VERSION_FILEDESCRIPTION) _VERSION_UNICODE("QIP"));
		pluginInfo.PluginAuthor     = ::SysAllocString(VERSION_COMPANY_NAME_U);
	}

	return &pluginInfo;
}

STDMETHODIMP_(VOID) CQipPlugin::OnQipMessage(PluginMessage* plugMsg)
{
	switch(plugMsg->Msg)
	{
		// Here you can start plugin work, create any forms, objects etc...
		// Note that if plugin is Disabled, it will not receive this message.
		// Instead of this msg it will receive PM_PLUGIN_ENABLE if user will enable this plugin in options
		case PM_PLUGIN_RUN:
			getStatus();
			onStart();
		break;

		// QIP closing, free plugin resources and finish plugin work}
		case PM_PLUGIN_QUIT:
			onStop();
			DestroyIcon(bInfo.BtnIcon);
			SysFreeString(bInfo.BtnHint);
		break;

		// Plugin was disabled in qip options, after this, this plugin will not receive
		// any QIP messages (excepting PM_PLUGIN_ENABLE and PM_PLUGIN_QUIT) and
		// any plugin message to qip core will be ignored, but plugin will stay loaded into memory.
		// Any connections and forms have to be closed.
		case PM_PLUGIN_DISABLE:
			onStop();
		break;

		// The same message like PM_PLUGIN_RUN but when plugin was enabled in
		// options and after that plugin will start receive messages from QIP
		case PM_PLUGIN_ENABLE:
			getStatus();
			onStart();
		break;

		case PM_PLUGIN_XSTATUS_CHANGED:
			m_nUserPicture        = plugMsg->WParam;
			m_bstrUserStatus      = (LPOLESTR)IntToPtr(plugMsg->LParam);
			m_bstrUserDescription = (LPOLESTR)IntToPtr(plugMsg->NParam);
		break;

		case PM_PLUGIN_CAN_ADD_BTNS:
			onButtonAdd();
		break;

		case PM_PLUGIN_MSG_BTN_CLICK:
			onButtonClick(plugMsg);
		break;

		case PM_PLUGIN_OPTIONS:
			plugMsg->Result = (int)onOptions((HWND)plugMsg->NParam);
		break;
	}
}

void
CQipPlugin::UpgradeOptions()
{
	// Ver 1 options are:
	//
	// Param1 = options version
	// Bool1  = True to enable geo status
	// Wstr1  = Wi2geo network user name or phone number
	// Wstr2  = Wi2geo network password md5 hash
	//
	if (m_pPluginSpecific->Param1 < 1)
	{
		m_pPluginSpecific->Param1 = 1;
		m_pPluginSpecific->Bool1  = true;
	}
}

void CQipPlugin::onStart()
{
	m_pPluginSpecific = m_pPluginService->PluginOptions(pluginInfo.DllHandle);

	if (NULL != m_pPluginSpecific)
		UpgradeOptions();

	Start();
}

void CQipPlugin::onStop()
{
	if (!m_hPollingThread)
		return;

	Stop();
}

void CQipPlugin::onButtonAdd()
{
	bInfo.BtnPNG = NULL;
	bInfo.BtnHint = SysAllocString(L"Послать мои координаты");
	bInfo.BtnIcon = WTL::AtlLoadIcon(IDI_ICON1);

	PluginMessage retMsg;
	retMsg.Msg = PM_PLUGIN_ADD_BTN;
	retMsg.DllHandle = pluginInfo.DllHandle;
	retMsg.WParam = PtrToInt(&bInfo);
	retMsg.LParam = NULL;
	retMsg.NParam = NULL;
	retMsg.Result = 0;

	m_pPluginService->OnPluginMessage ( &retMsg );
	actionId = retMsg.Result;
}

void CQipPlugin::onButtonClick(PluginMessage* plugMsg)
{
	if (plugMsg->WParam != actionId)
		return;

	sendMessage(plugMsg->Result, plugMsg->LParam);
}

INT_PTR CQipPlugin::onOptions
	( IN HWND hWndOwner
	)
{
	if (!m_pPluginSpecific)
		return 0;

	if (!::IsWindow(hWndOwner))
	{
		// Older qip does not pass owner window handle.
		//
		hWndOwner = ::GetDesktopWindow();
	}

	CQipOptions dlgOptions;
	INT_PTR nRet = dlgOptions.DoModal(hWndOwner, PtrToLong(m_pPluginSpecific));
	if (IDOK == nRet)
		Login();
	return nRet;
}

void CQipPlugin::sendMessage(int protocolHandle, int accountName)
{
	ATL::CComBSTR bstrLocation(ATL::CA2WEX<256>(
		GetLocation(FMT_PLAIN_TEXT).c_str(), CP_UTF8));

	PluginMessage retMsg;
	retMsg.Msg = PM_PLUGIN_SEND_IM;
	retMsg.DllHandle = pluginInfo.DllHandle;
	retMsg.WParam = protocolHandle;
	retMsg.LParam = accountName;
	retMsg.NParam = PtrToInt(bstrLocation.m_str);
	retMsg.Result = 0;
	m_pPluginService->OnPluginMessage(&retMsg);

	if (!retMsg.Result) {
		// ReportError(_T("Send failed"));
	};
}
void CQipPlugin::getStatus()
{
	PluginMessage getMsg;
	getMsg.Msg = PM_PLUGIN_XSTATUS_GET;
	getMsg.DllHandle = pluginInfo.DllHandle;
	m_pPluginService->OnPluginMessage(&getMsg);

	m_nUserPicture        = getMsg.WParam;
	m_bstrUserStatus      = (LPOLESTR)IntToPtr(getMsg.LParam);
	m_bstrUserDescription = (LPOLESTR)IntToPtr(getMsg.NParam);
}
void
CQipPlugin::OnSetLocation
	( IN const std::string& strLocation
	)
{
	if (!m_pPluginSpecific || !m_pPluginSpecific->Bool1)
		return;

	PluginMessage setMsg;
	setMsg.Msg = PM_PLUGIN_XSTATUS_UPD;
	setMsg.DllHandle = pluginInfo.DllHandle;
	ATL::CA2WEX<256> wzLocation(strLocation.c_str(), CP_UTF8);

	if (0 == m_nUserPicture)
		m_nUserPicture = 27;

	if (0 == m_bstrUserStatus.Length())
		m_bstrUserStatus = OLESTR("Координаты по Wi2Geo");

	setMsg.WParam = m_nUserPicture;
	setMsg.LParam = PtrToInt(m_bstrUserStatus.m_str);
	setMsg.NParam = PtrToInt((LPCWSTR)wzLocation);
	setMsg.Result = 0;
	m_pPluginService->OnPluginMessage(&setMsg);
}

/////////////////////////////////////////////////////
// Dll Exports
/////////////////////////////////////////////////////

EXTERN_C STDMETHODIMP
CreateInfiumPLUGIN
	( OUT IQIPPlugin** ppPlugin
	, IN IQIPPluginService* pPluginService
	)
{
	ATLTRACE(_T(__FUNCTION__) _T(": 0x%08X, 0x%08X\n")
		, ppPlugin, pPluginService);

	if (NULL == ppPlugin)
		return E_POINTER;

	if (NULL == pPluginService)
		return E_INVALIDARG;

	CoQipPlugin *pPlugin;
	HRESULT hr;

	hr = CoQipPlugin::CreateInstance(&pPlugin);
	if (SUCCEEDED(hr))
	{
		pPlugin->AddRef();
		hr = pPlugin->Init(pPluginService);
		if (SUCCEEDED(hr))
			hr = pPlugin->QueryInterface(IID_IUnknown, (void**)ppPlugin);
		pPlugin->Release();
	}

	if (FAILED(hr))
		ATLTRACE(_T("Failed to create plugin: 0x%08X\n"), hr);

	return hr;
}
